#include "eqctrlwidget.h"
#include "dm/filter.h"
#include <QDebug>

EqCtrlWidget::EqCtrlWidget(const EQ &initArg, const int &flag, const bool &showLabel, QWidget *parent)
    : QWidget{parent}
    , m_initArg{initArg}
    , m_flag{flag}
{
    auto layout = new QGridLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);

    textLabel = new QLabel(QString::number(m_flag + 1), this);
    freqLabel = new QLabel(tr("Freq"), this);
    qLabel = new QLabel(tr("Q"), this);
    gainLabel = new QLabel(tr("Gain"), this);
    typeLabel = new QLabel(tr("Type"), this);

    if (!showLabel) {
        freqLabel->hide();
        qLabel->hide();
        gainLabel->hide();
        typeLabel->hide();
    }

    checkBox = new QCheckBox(this);
    slider = new QSlider(this);
    freqSpinBox = new QSpinBox(this);
    qSpinBox = new QValueSpinBox(this);
    gainSpinBox = new QDoubleSpinBox(this);
    typeComboBox = new QComboBox(this);    

    layout->addWidget(textLabel, 0, 1, Qt::AlignHCenter | Qt::AlignBottom);
    layout->addWidget(freqLabel, 3, 0);
    layout->addWidget(qLabel, 4, 0);
    layout->addWidget(gainLabel, 5, 0);
    layout->addWidget(typeLabel, 6, 0);

    layout->addWidget(checkBox, 1, 1, Qt::AlignHCenter);
    layout->addWidget(slider, 2, 1, Qt::AlignHCenter);
    layout->addWidget(freqSpinBox, 3, 1, Qt::AlignHCenter);
    layout->addWidget(qSpinBox, 4, 1, Qt::AlignHCenter);
    layout->addWidget(gainSpinBox, 5, 1, Qt::AlignHCenter);
    layout->addWidget(typeComboBox, 6, 1, Qt::AlignHCenter);

    slider->setFixedHeight(200);

    constexpr auto boxWidth = 100;
    freqSpinBox->setFixedWidth(boxWidth);
    qSpinBox->setFixedWidth(boxWidth);
    gainSpinBox->setFixedWidth(boxWidth);
    typeComboBox->setFixedWidth(boxWidth);

    slider->setRange(EQ_GAIN_MIN / EQ_GAIN_STEP, EQ_GAIN_MAX / EQ_GAIN_STEP);
    slider->setValue(EQ_GAIN_DEFAULT);
    slider->setTickInterval(EQ_GAIN_LABEL_STEP / EQ_GAIN_STEP);
    slider->setTickPosition(QSlider::TicksBothSides);

    freqSpinBox->setRange(EQ_FREQUENCY_MIN, EQ_FREQUENCY_MAX);

    gainSpinBox->setSingleStep(EQ_GAIN_STEP);
    gainSpinBox->setDecimals(EQ_GAIN_DECIMAL);
    gainSpinBox->setRange(EQ_GAIN_MIN, EQ_GAIN_MAX);

    for (auto it = EQ_TYPE.begin(); it < EQ_TYPE.end(); ++it) {
        typeComboBox->addItem(tr(*it));
    }

    connect(checkBox, &QCheckBox::clicked, this, &EqCtrlWidget::init);
    connect(slider, &QSlider::valueChanged, this, &EqCtrlWidget::sliderValueChanged);
    connect(this, &EqCtrlWidget::qValueChanged, qSpinBox, &QSpinBox::setValue);
    connect(freqSpinBox, QOverload<int>::of(&QValueSpinBox::valueChanged), this, &EqCtrlWidget::emitCurrentValue);
    connect(qSpinBox, QOverload<int>::of(&QValueSpinBox::valueChanged), this, &EqCtrlWidget::emitCurrentValue);
    connect(gainSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EqCtrlWidget::emitCurrentValue);
    connect(typeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EqCtrlWidget::emitCurrentValue);

    init();
}

EQ EqCtrlWidget::getCurrentValue() const
{
    EQ arg;
    arg.freq = freqSpinBox->value();
    // arg.q = qSpinBox->value();
    arg.bw = qSpinBox->value();
    arg.gain = gainSpinBox->value();
    arg.type = static_cast<EQType>(typeComboBox->currentIndex());
    return arg;
}

void EqCtrlWidget::reset()
{
    init();
    typeComboBox->setCurrentText(tr(EQ_TYPE.at(static_cast<uint16_t>(m_initArg.type))));
}

void EqCtrlWidget::setFreqQain(const std::pair<double, double> &pair)
{
    freqSpinBox->setValue(pair.first);
    gainSpinBox->setValue(pair.second);
    slider->setValue(gainSpinBox->value() / EQ_GAIN_STEP);
}

void EqCtrlWidget::init()
{
    freqSpinBox->setValue(m_initArg.freq);
    qSpinBox->setValue(m_initArg.bw);
    gainSpinBox->setValue(m_initArg.gain);
    slider->setValue(gainSpinBox->value() / EQ_GAIN_STEP);
    checkBox->setChecked(true);
}

void EqCtrlWidget::sliderValueChanged(const int &value)
{
    gainSpinBox->setValue(value * EQ_GAIN_STEP);
    if (EQ_GAIN_DEFAULT == value) {
        checkBox->setChecked(true);
    }
    else {
        checkBox->setChecked(false);
    }
    emitCurrentValue();
}

void EqCtrlWidget::emitCurrentValue()
{
    emit stateChanged(getCurrentValue());
}

